package com.yuanxiao.filter;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.*;

/**
 * 定义全局路由器,会对所有的路由生效
 */
@Slf4j
@Component
public class BlackListFilter implements GlobalFilter, Ordered  {

    //模拟黑名单
    private static List<String> blackList =new ArrayList<>();

    private static Map<String, HashMap> ipMap = new HashMap<String, HashMap>();

   /* static {
        blackList.add("0:0:0:0:0:0:0:1");
    }*/

    @Value("${ip.maxtimes}")
    private Integer times;
    @Value("${ip.expiretime}")
    private Integer addtime;
    /**
     *过滤器核心方法
     * @param exchange 封装了request和response对象的上下文
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //判断客户端IP是否在黑名单中
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String url = request.getURI().getPath();
        if (!url.contains("/user/register")){
            //只对注册限制
            return chain.filter(exchange);
        }



        String clientIp = request.getRemoteAddress().getHostString();

        //先把ip 计入一个map<ip,map> 来统计其再一定时间内的访问次数.达到一定次数后,放入黑名单数组,并拦截.次数和时间通过config获取
        HashMap hashMap = ipMap.get(clientIp);
        if(hashMap == null){
            HashMap<String, Object> stringObjectHashMap = new HashMap<>();
            stringObjectHashMap.put("times",1);
            stringObjectHashMap.put("time", DateUtils.addMinutes(new Date(),addtime));
            ipMap.put(clientIp,stringObjectHashMap);
        }else {
            Date time = (Date) hashMap.get("time");
            if(time.compareTo(new Date())>=0){//比当前时间大 还没失效
                Integer i=  (Integer) hashMap.get("times");
                if(i>=times){//再规定时间超过了限制,加入黑名单
                    blackList.add(clientIp);
                }else {
                    hashMap.put("times",i+1);//没超过 就+1
                }
            }else {//失效了 重新累积
                hashMap.put("times",1);
                hashMap.put("time", DateUtils.addMinutes(new Date(),addtime));
                Iterator<String> iterator = blackList.iterator();
                while (iterator.hasNext()){
                    String next = iterator.next();
                    if(next.equals(clientIp)){
                        iterator.remove();
                    }
                }
            }
        }

        //拿着clientip去黑名单中查询
        if(blackList.contains(clientIp)){
            //拒绝
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            log.debug("=========>IP"+clientIp+"再黑名单中");
            String date="Rsquest be denied";
            DataBuffer wrap = response.bufferFactory().wrap(date.getBytes());
            return response.writeWith(Mono.just(wrap));
        }
        return chain.filter(exchange);
    }

    /**
     * 返回值表示当前过滤器的优先级,数值越小,优先级越高
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}
